home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / mac / files / t_sys5 / unixcpio.gz / unixnet.cpio / lapb.c < prev    next >
C/C++ Source or Header  |  1994-07-11  |  15KB  |  633 lines

  1. /* Link Access Procedures Balanced (LAPB) - with changes for rational
  2.  * behavior over packet radio
  3.  */
  4. #include "global.h"
  5. #include "mbuf.h"
  6. #include "timer.h"
  7. #include "ax25.h"
  8. #include "lapb.h"
  9. #include "iface.h"
  10. #ifdef    UNIX
  11. #include <memory.h>
  12. #endif
  13.  
  14. /* Process incoming frames */
  15. int
  16. lapb_input(axp,cmdrsp,bp)
  17. struct ax25_cb *axp;        /* Link control structure */
  18. char cmdrsp;            /* Command/response flag */
  19. struct mbuf *bp;        /* Rest of frame, starting with ctl */
  20. {
  21.     int16 ftype();
  22.     void lapbstate();
  23.     char control;
  24.     char class;        /* General class (I/S/U) of frame */
  25.     int16 type;        /* Specific type (I/RR/RNR/etc) of frame */
  26.     char pf;        /* extracted poll/final bit */
  27.     char poll = 0;
  28.     char final = 0;
  29.     int nr;            /* ACK number of incoming frame */
  30.     int ns;            /* Seq number of incoming frame */
  31.     char tmp;
  32.  
  33.     if(bp == NULLBUF || axp == NULLAX25){
  34.         free_p(bp);
  35.         return -1;
  36.     }
  37.  
  38.     /* Extract the various parts of the control field for easy use */
  39.     control = pullchar(&bp);
  40.     type = ftype(control);
  41.     class = type & 0x3;
  42.     pf = control & PF;
  43.     /* Check for polls and finals */
  44.     if(pf){
  45.         switch(cmdrsp){
  46.         case COMMAND:
  47.             poll = YES;
  48.             break;
  49.         case RESPONSE:
  50.             final = YES;
  51.             break;
  52.         }
  53.     }
  54.     /* Extract sequence numbers, if present */
  55.     switch(class){
  56.     case I:
  57.     case I+2:
  58.         ns = (control >> 1) & MMASK;
  59.     case S:    /* Note fall-thru */
  60.         nr = (control >> 5) & MMASK;
  61.         break;
  62.     }
  63.     /* This section follows the SDL diagrams by K3NA fairly closely */
  64.     switch(axp->state){
  65.     case DISCONNECTED:
  66.         switch(type){
  67.         case SABM:    /* Initialize or reset link */
  68.             sendctl(axp,RESPONSE,UA|pf);    /* Always accept */
  69.             clr_ex(axp);
  70.             axp->unack = axp->vr = axp->vs = 0;
  71.             lapbstate(axp,CONNECTED);/* Resets state counters */
  72.             start_timer(&axp->t3);
  73.             break;
  74.         case DM:    /* Ignore to avoid infinite loops */
  75.             break;
  76.         default:    /* All others get DM */
  77.             sendctl(axp,RESPONSE,DM|pf);
  78.             break;
  79.         }
  80.         break;
  81.     case SETUP:
  82.         switch(type){
  83.         case SABM:    /* Simultaneous open */
  84.             sendctl(axp,RESPONSE,UA|pf);
  85.             break;
  86.         case DISC:
  87.             sendctl(axp,RESPONSE,DM|pf);
  88.             break;
  89.         case UA:    /* Connection accepted */
  90.             /* Note: xmit queue not cleared */
  91.             stop_timer(&axp->t1);
  92.             start_timer(&axp->t3);
  93.             axp->unack = axp->vr = axp->vs = 0;
  94.             lapbstate(axp,CONNECTED);
  95.             break;            
  96.         case DM:    /* Connection refused */
  97.             free_q(&axp->txq);
  98.             stop_timer(&axp->t1);
  99.             lapbstate(axp,DISCONNECTED);
  100.             break;
  101.         default:    /* All other frames ignored */
  102.             break;
  103.         }
  104.         break;
  105.     case DISCPENDING:
  106.         switch(type){
  107.         case SABM:
  108.             sendctl(axp,RESPONSE,DM|pf);
  109.             break;
  110.         case DISC:
  111.             sendctl(axp,RESPONSE,UA|pf);
  112.             break;
  113.         case UA:
  114.         case DM:
  115.             stop_timer(&axp->t1);
  116.             lapbstate(axp,DISCONNECTED);
  117.             break;
  118.         default:    /* Respond with DM only to command polls */
  119.             if(poll)
  120.                 sendctl(axp,RESPONSE,DM|pf);
  121.             break;
  122.         }
  123.         break;
  124.     case CONNECTED:
  125.         switch(type){
  126.         case SABM:
  127.             sendctl(axp,RESPONSE,UA|pf);
  128.             clr_ex(axp);
  129.             free_q(&axp->txq);
  130.             stop_timer(&axp->t1);
  131.             start_timer(&axp->t3);
  132.             axp->unack = axp->vr = axp->vs = 0;
  133.             lapbstate(axp,CONNECTED); /* Purge queues */
  134.             break;
  135.         case DISC:
  136.             free_q(&axp->txq);
  137.             sendctl(axp,RESPONSE,UA|pf);
  138.             stop_timer(&axp->t1);
  139.             stop_timer(&axp->t3);
  140.             lapbstate(axp,DISCONNECTED);
  141.             break;
  142. /* This code is cribbed from the NOS version, in order to make a */
  143. /* temporary fix to a pathological looping behavior during connect (dmf) */
  144.         case DM:
  145.             lapbstate(axp,DISCONNECTED);
  146.             break;
  147.         case UA:
  148.             est_link(axp);
  149.             lapbstate(axp,SETUP);    /* Re-establish */    
  150.             break;
  151. /* End of cribbed code (dmf) */            
  152.         case FRMR:
  153.             est_link(axp);
  154.             lapbstate(axp,SETUP);    /* Re-establish link */
  155.             break;
  156.         case RR:
  157.         case RNR:
  158.             axp->remotebusy = (control == RNR) ? YES : NO;
  159.             if(poll)
  160.                 enq_resp(axp);
  161.             (void)ackours(axp,nr);
  162.             break;
  163.         case REJ:
  164.             axp->remotebusy = NO;
  165.             if(poll)
  166.                 enq_resp(axp);
  167.             (void)ackours(axp,nr);
  168.             stop_timer(&axp->t1);
  169.             start_timer(&axp->t3);
  170.             /* This may or may not actually invoke transmission,
  171.              * depending on whether this REJ was caused by
  172.              * our losing his prior ACK.
  173.              */
  174.             inv_rex(axp);
  175.             break;    
  176.         case I:
  177.             (void)ackours(axp,nr); /** == -1) */
  178.             if(len_mbuf(axp->rxq) >= axp->window){
  179.                 /* Too bad he didn't listen to us; he'll
  180.                  * have to resend the frame later. This
  181.                  * drastic action is necessary to avoid
  182.                  * deadlock.
  183.                  */
  184.                 if(poll)
  185.                     sendctl(axp,RESPONSE,RNR|pf);
  186.                 free_p(bp);
  187.                 bp = NULLBUF;
  188.                 break;
  189.             }
  190.             /* Reject or ignore I-frames with receive sequence number errors */
  191.             if(ns != axp->vr){
  192.                 if(axp->proto == V1 || !axp->rejsent){
  193.                     axp->rejsent = YES;
  194.                     sendctl(axp,RESPONSE,REJ | pf);
  195.                 }
  196.                 axp->response = 0;
  197.                 stop_timer(&axp->t2);
  198.                 break;
  199.             }
  200.             axp->rejsent = NO;
  201.             axp->vr = (axp->vr+1) & MMASK;
  202.             tmp = len_mbuf(axp->rxq) >= axp->window ? RNR : RR;
  203.             if(poll){
  204.                 sendctl(axp,RESPONSE,tmp|PF);
  205.             } else {
  206.                 axp->response = tmp;
  207.                 start_timer(&axp->t2);
  208.             }
  209.             procdata(axp,bp);
  210.             bp = NULLBUF;
  211.             break;
  212.         default:    /* All others ignored */
  213.             break;
  214.         }
  215.         break;
  216.     case RECOVERY:
  217.         switch(type){
  218.         case SABM:
  219.             sendctl(axp,RESPONSE,UA|pf);
  220.             clr_ex(axp);
  221.             stop_timer(&axp->t1);
  222.             start_timer(&axp->t3);
  223.             axp->unack = axp->vr = axp->vs = 0;
  224.             lapbstate(axp,CONNECTED); /* Purge queues */
  225.             break;
  226.         case DISC:
  227.             free_q(&axp->txq);
  228.             sendctl(axp,RESPONSE,UA|pf);
  229.             stop_timer(&axp->t1);
  230.             stop_timer(&axp->t3);
  231.             axp->response = UA;
  232.             lapbstate(axp,DISCONNECTED);
  233.             break;
  234. /* This code is cribbed from the NOS version, in order to make a */
  235. /* temporary fix to a pathological looping behavior during connect (dmf) */
  236.         case DM:
  237.             lapbstate(axp,DISCONNECTED);
  238.             break;
  239.         case UA:
  240.             est_link(axp);
  241.             lapbstate(axp,SETUP);    /* Re-establish */    
  242.             break;
  243. /* End of cribbed code (dmf) */            
  244.         case FRMR:
  245.             est_link(axp);
  246.             lapbstate(axp,SETUP);    /* Re-establish link */
  247.             break;
  248.         case RR:
  249.         case RNR:
  250.             axp->remotebusy = (control == RNR) ? YES : NO;
  251.             if(axp->proto == V1 || final){
  252.                 stop_timer(&axp->t1);
  253.                 (void)ackours(axp,nr);
  254.                 if(axp->unack != 0){
  255.                     inv_rex(axp);
  256.                 } else {
  257.                     start_timer(&axp->t3);
  258.                     lapbstate(axp,CONNECTED);
  259.                 }
  260.             } else {
  261.                 if(poll)
  262.                     enq_resp(axp);
  263.                 (void)ackours(axp,nr);
  264.                 /* Keep timer running even if all frames
  265.                  * were acked, since we must see a Final
  266.                  */
  267.                 if(!run_timer(&axp->t1))
  268.                     start_timer(&axp->t1);
  269.             }
  270.             break;
  271.         case REJ:
  272.             axp->remotebusy = NO;
  273.             /* Don't insist on a Final response from the old proto */
  274.             if(axp->proto == V1 || final){
  275.                 stop_timer(&axp->t1);
  276.                 (void)ackours(axp,nr);
  277.                 if(axp->unack != 0){
  278.                     inv_rex(axp);
  279.                 } else {
  280.                     start_timer(&axp->t3);
  281.                     lapbstate(axp,CONNECTED);
  282.                 }
  283.             } else {
  284.                 if(poll)
  285.                     enq_resp(axp);
  286.                 (void)ackours(axp,nr);
  287.                 if(axp->unack != 0){
  288.                     /* This is certain to trigger output */
  289.                     inv_rex(axp);
  290.                 }
  291.                 /* A REJ that acks everything but doesn't
  292.                  * have the F bit set can cause a deadlock.
  293.                  * So make sure the timer is running.
  294.                  */
  295.                 if(!run_timer(&axp->t1))
  296.                     start_timer(&axp->t1);
  297.             }
  298.             break;
  299.         case I:
  300.             (void)ackours(axp,nr); /** == -1) */
  301.             /* Make sure timer is running, since an I frame
  302.              * cannot satisfy a poll
  303.              */
  304.             if(!run_timer(&axp->t1))
  305.                 start_timer(&axp->t1);
  306.             if(len_mbuf(axp->rxq) >= axp->window){
  307.                 /* Too bad he didn't listen to us; he'll
  308.                  * have to resend the frame later. This
  309.                  * drastic action is necessary to avoid
  310.                  * memory deadlock.
  311.                  */
  312.                 sendctl(axp,RESPONSE,RNR | pf);
  313.                 free_p(bp);
  314.                 bp = NULLBUF;
  315.                 break;
  316.             }
  317.             /* Reject or ignore I-frames with receive sequence number errors */
  318.             if(ns != axp->vr){
  319.                 if(axp->proto == V1 || !axp->rejsent){
  320.                     axp->rejsent = YES;
  321.                     sendctl(axp,RESPONSE,REJ | pf);
  322.                 }
  323.                 axp->response = 0;
  324.                 stop_timer(&axp->t2);
  325.                 break;
  326.             }
  327.             axp->rejsent = NO;
  328.             axp->vr = (axp->vr+1) & MMASK;
  329.             tmp = len_mbuf(axp->rxq) >= axp->window ? RNR : RR;
  330.             if(poll){
  331.                 sendctl(axp,RESPONSE,tmp|PF);
  332.             } else {
  333.                 axp->response = tmp;
  334.                 start_timer(&axp->t2);
  335.             }
  336.             procdata(axp,bp);
  337.             bp = NULLBUF;
  338.             break;
  339.         default:
  340.             break;        /* Ignored */
  341.         }
  342.         break;
  343.     case FRAMEREJECT:
  344.         switch(type){
  345.         case SABM:
  346.             sendctl(axp,RESPONSE,UA|pf);
  347.             clr_ex(axp);
  348.             axp->unack = axp->vr = axp->vs = 0;
  349.             stop_timer(&axp->t1);
  350.             start_timer(&axp->t3);
  351.             lapbstate(axp,CONNECTED);
  352.             break;
  353.         case DISC:
  354.             free_q(&axp->txq);
  355.             sendctl(axp,RESPONSE,UA|pf);
  356.             stop_timer(&axp->t1);
  357.             lapbstate(axp,DISCONNECTED);
  358.             break;
  359.         case DM:
  360.             stop_timer(&axp->t1);
  361.             lapbstate(axp,DISCONNECTED);
  362.             break;
  363.         default:
  364.             frmr(axp,0,0);
  365.             break;
  366.         }
  367.         break;
  368.     }
  369.     free_p(bp);    /* In case anything's left */
  370.  
  371.     /* See if we can send some data, perhaps piggybacking an ack.
  372.      * If successful, lapb_output will clear axp->response.
  373.      */
  374.     lapb_output(axp);
  375.  
  376.     /* Empty the trash */
  377.     if(axp->state == DISCONNECTED)
  378.         del_ax25(axp);
  379.     return 0;
  380. }
  381. /* Handle incoming acknowledgements for frames we've sent.
  382.  * Free frames being acknowledged.
  383.  * Return -1 to cause a frame reject if number is bad, 0 otherwise
  384.  */
  385. static int
  386. ackours(axp,n)
  387. struct ax25_cb *axp;
  388. char n;
  389. {    
  390.     struct mbuf *bp;
  391.     int acked = 0;    /* Count of frames acked by this ACK */
  392.     int oldest;    /* Seq number of oldest unacked I-frame */
  393.  
  394.     /* Free up acknowledged frames by purging frames from the I-frame
  395.      * transmit queue. Start at the remote end's last reported V(r)
  396.      * and keep going until we reach the new sequence number.
  397.      * If we try to free a null pointer,
  398.      * then we have a frame reject condition.
  399.      */
  400.     oldest = (axp->vs - axp->unack) & MMASK;
  401.     while(axp->unack != 0 && oldest != n){
  402.         if((bp = dequeue(&axp->txq)) == NULLBUF){
  403.             /* Acking unsent frame */
  404.             return -1;
  405.         }
  406.         free_p(bp);
  407.         axp->unack--;
  408.         acked++;
  409.         axp->retries = 0;
  410.         oldest = (oldest + 1) & MMASK;
  411.     }
  412.     if(axp->unack == 0){
  413.         /* All frames acked, stop timeout */
  414.         stop_timer(&axp->t1);
  415.         start_timer(&axp->t3);
  416.     } else if(acked != 0) { 
  417.         /* Partial ACK; restart timer */
  418.         start_timer(&axp->t1);
  419.     }
  420.     /* If user has set a transmit upcall, indicate how many frames
  421.      * may be queued
  422.      */
  423.     if(acked != 0 && axp->t_upcall != NULLVFP)
  424.         (*axp->t_upcall)(axp,axp->paclen * (axp->maxframe - axp->unack));
  425.  
  426.     return 0;
  427. }
  428.  
  429. /* Establish data link */
  430. est_link(axp)
  431. struct ax25_cb *axp;
  432. {
  433.     clr_ex(axp);
  434.     axp->retries = 0;
  435.     sendctl(axp,COMMAND,SABM|PF);
  436.     stop_timer(&axp->t3);
  437.     start_timer(&axp->t1);
  438. }
  439. /* Clear exception conditions */
  440. clr_ex(axp)
  441. struct ax25_cb *axp;
  442. {
  443.     axp->remotebusy = NO;
  444.     axp->rejsent = NO;
  445.     axp->response = 0;
  446.     stop_timer(&axp->t3);
  447. }
  448. /* Enquiry response */
  449. enq_resp(axp)
  450. struct ax25_cb *axp;
  451. {
  452.     char ctl;
  453.  
  454.     ctl = len_mbuf(axp->rxq) >= axp->window ? RNR|PF : RR|PF;    
  455.     sendctl(axp,RESPONSE,ctl);
  456.     axp->response = 0;
  457.     stop_timer(&axp->t3);
  458. }
  459. /* Invoke retransmission */
  460. inv_rex(axp)
  461. struct ax25_cb *axp;
  462. {
  463.     axp->vs -= axp->unack;
  464.     axp->vs &= MMASK;
  465.     axp->unack = 0;
  466. }
  467. /* Generate Frame Reject (FRMR) response
  468.  * If reason != 0, this is the initial error frame
  469.  * If reason == 0, resend the last error frame
  470.  */
  471. int
  472. frmr(axp,control,reason)
  473. register struct ax25_cb *axp;
  474. char control;
  475. char reason;
  476. {
  477.     struct mbuf *frmrinfo;
  478.     register char *cp;
  479.     void lapbstate();
  480.  
  481.     if(reason != 0){
  482.         cp = axp->frmrinfo;
  483.         *cp++ = control;
  484.         *cp++ =  axp->vr << 5 || axp->vs << 1;
  485.         *cp = reason;
  486.     }
  487.     if((frmrinfo = alloc_mbuf(3)) == NULLBUF)
  488.         return -1;    /* No memory */
  489.     frmrinfo->cnt = 3;
  490.     memcpy(frmrinfo->data,axp->frmrinfo,3);
  491.     return sendframe(axp,RESPONSE,FRMR|(control&PF),frmrinfo);
  492. }
  493.  
  494. /* Send S or U frame to currently connected station */
  495. int
  496. sendctl(axp,cmdrsp,cmd)
  497. struct ax25_cb *axp;
  498. char cmdrsp,cmd;
  499. {
  500.     int16 ftype();
  501.  
  502.     if((ftype(cmd) & 0x3) == S)    /* Insert V(R) if S frame */
  503.         cmd |= (axp->vr << 5);
  504.     return sendframe(axp,cmdrsp,cmd,NULLBUF);
  505. }
  506. /* Start data transmission on link, if possible
  507.  * Return number of frames sent
  508.  */
  509. int
  510. lapb_output(axp)
  511. register struct ax25_cb *axp;
  512. {
  513.     register struct mbuf *bp;
  514.     struct mbuf *tbp;
  515.     char control;
  516.     int sent = 0;
  517.     int i;
  518.  
  519.     if(axp == NULLAX25
  520.      || (axp->state != RECOVERY && axp->state != CONNECTED)
  521.      || axp->remotebusy)
  522.         return 0;
  523.  
  524.     /* Dig into the send queue for the first unsent frame */
  525.     bp = axp->txq;
  526.     for(i = 0; i < axp->unack; i++){
  527.         if(bp == NULLBUF)
  528.             break;    /* Nothing to do */
  529.         bp = bp->anext;
  530.     }
  531.     /* Start at first unsent I-frame, stop when either the
  532.      * number of unacknowledged frames reaches the maxframe limit,
  533.      * or when there are no more frames to send
  534.      */
  535.     while(bp != NULLBUF && axp->unack < axp->maxframe){
  536.         control = I | (axp->vs++ << 1) | (axp->vr << 5);
  537.         axp->vs &= MMASK;
  538.         dup_p(&tbp,bp,0,len_mbuf(bp));
  539.         if(tbp == NULLBUF)
  540.             return sent;    /* Probably out of memory */
  541.         sendframe(axp,COMMAND,control,tbp);
  542.         axp->unack++;
  543.         /* We're implicitly acking any data he's sent, so stop any
  544.          * delayed ack
  545.          */
  546.         axp->response = 0;
  547.         stop_timer(&axp->t2);
  548.         if(!run_timer(&axp->t1)){
  549.             stop_timer(&axp->t3);
  550.             start_timer(&axp->t1);
  551.         }
  552.         sent++;
  553.         bp = bp->anext;
  554.     }
  555.     return sent;
  556. }
  557. /* Set new link state.
  558.  * If the new state is disconnected, also free the link control block.
  559.  */
  560. void
  561. lapbstate(axp,s)
  562. struct ax25_cb *axp;
  563. int s;
  564. {
  565.     int oldstate;
  566.  
  567.     oldstate = axp->state;
  568.     axp->state = s;
  569.     if(s == DISCONNECTED){
  570.         stop_timer(&axp->t1);
  571.         stop_timer(&axp->t2);
  572.         stop_timer(&axp->t3);
  573.         free_q(&axp->txq);
  574.     }
  575.     /* Don't bother the client unless the state is really changing */
  576.     if(oldstate != s && axp->s_upcall != NULLVFP)
  577.         (*axp->s_upcall)(axp,oldstate,s);
  578. }
  579. /* Process a valid incoming I frame */
  580. static
  581. procdata(axp,bp)
  582. struct ax25_cb *axp;
  583. struct mbuf *bp;
  584. {
  585.     char pid;
  586.     int ip_route();
  587.  
  588.     /* Extract level 3 PID */
  589.     if(pullup(&bp,&pid,1) != 1)
  590.         return;    /* No PID */
  591.  
  592.     switch(pid & (PID_FIRST|PID_LAST)){
  593.     case PID_FIRST:
  594.         /* "Shouldn't happen", but flush any accumulated frags */
  595.         free_p(axp->rxasm);
  596.         axp->rxasm = NULLBUF;
  597.     case 0:    /* Note fall-thru */
  598.         /* Beginning or middle of message, just accumulate */
  599.         append(&axp->rxasm,bp);
  600.         return;
  601.     case PID_LAST:
  602.         /* Last frame of multi-frame message; extract it */
  603.         append(&axp->rxasm,bp);
  604.         bp = axp->rxasm;
  605.         axp->rxasm = NULLBUF;
  606.         break;
  607.     case PID_FIRST|PID_LAST:
  608.         /* Do nothing with reassembly queue, allowing single-frame
  609.          * messages to be interspersed with fragments of multi-frame
  610.          * messages
  611.          */
  612.         break;
  613.     }
  614.     /* Last frame in sequence; kick entire message upstairs */
  615.     switch(pid & PID_PID){
  616.     case PID_IP:        /* DoD Internet Protocol */
  617.         ip_route(bp,0);
  618.         break;
  619.     case PID_NO_L3:        /* Enqueue for application */
  620.         append(&axp->rxq,bp);
  621.         if(axp->r_upcall != NULLVFP)
  622.             (*axp->r_upcall)(axp,len_mbuf(axp->rxq));
  623.         break;    
  624.     case PID_NETROM:
  625.         nr_route(bp,axp);
  626.         break;
  627.     default:        /* Note: ARP is invalid here */    
  628.         free_p(bp);
  629.         break;            
  630.     }
  631. }
  632.  
  633.